package controllers

import (
	"context"
	"net/http"

	"github.com/goravel/framework/auth"
	contractsauth "github.com/goravel/framework/contracts/auth"
	contractshttp "github.com/goravel/framework/contracts/http"
	"github.com/goravel/framework/facades"
	goravelhttp "github.com/goravel/framework/http"
	"github.com/goravel/framework/support/debug"
	"github.com/pkg/errors"
	"goravel/app/models"
	userlistproto "goravel/app/protos/users"
)

type UserlistController struct {
}

func NewUserlistController() *UserlistController {
	return &UserlistController{}
}

// @TODO: Add GetUserList function to get user list
// (*UserResponse, error)
func (r *UserlistController) GetUserList(ctx context.Context, req *userlistproto.UserRequest) (*userlistproto.UserResponse, error) {
	if req.GetToken() == "" {
		return &userlistproto.UserResponse{
			Code:    http.StatusUnauthorized,
			Message: "empty token",
		}, nil
	}

	httpCtx := goravelhttp.Background()
	token, err := r.refreshToken(httpCtx, req.GetToken())
	if err != nil {
		return &userlistproto.UserResponse{
			Code:    http.StatusUnauthorized,
			Message: err.Error(),
		}, nil
	}

	userlist, err := getUserList(httpCtx)
	if err != nil {
		return &userlistproto.UserResponse{
			Code:    http.StatusUnauthorized,
			Message: err.Error(),
		}, nil
	}
	var userprotolist []*userlistproto.User
	for _, user := range userlist {
		userprotolist = append(userprotolist, &userlistproto.User{
			Id:        uint64(user.ID),
			CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"),
			UpdatedAt: user.UpdatedAt.Format("2006-01-02 15:04:05"),
			Mobile:    user.Mobile,
			Password:  user.Password,
			Token:     token,
		})
	}
	return &userlistproto.UserResponse{
		Code: http.StatusOK,
		Data: userprotolist,
	}, nil
}

func (receiver *UserlistController) refreshToken(ctx contractshttp.Context, token string) (string, error) {
	var (
		payload *contractsauth.Payload
		err     error
	)
	if payload, err = facades.Auth().Parse(ctx, token); err != nil {
		if errors.Is(err, auth.ErrorTokenExpired) {
			token, err = facades.Auth().Refresh(ctx)
			if err != nil {
				return "", err
			}

			token = "Bearer " + token
		} else {
			return "", err
		}
	}

	debug.Dump(payload)

	return token, nil
}

func getUserList(ctx contractshttp.Context) ([]models.User, error) {
	var user models.User
	if err := facades.Auth().User(ctx, &user); err != nil {
		return nil, err
	}

	if user.ID == 0 {
		return nil, errors.New("no user found")
	}

	users := []models.User{}
	facades.Orm().Query().Model(&models.User{}).Find(&users)
	return users, nil
}
